package com.sugon.controller.spare;

import cn.afterturn.easypoi.entity.vo.TemplateExcelConstants;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import cn.afterturn.easypoi.view.PoiBaseView;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.sugon.annotation.AutoLog;
import com.sugon.annotation.LimitSubmit;
import com.sugon.annotation.NonBusinessParamValid;
import com.sugon.consts.DevRetreadStatus;
import com.sugon.dao.*;
import com.sugon.entity.DevTypeEntity;
import com.sugon.entity.SparePartEntity;
import com.sugon.entity.SpareStorePosEntity;
import com.sugon.entity.vo.SparePartLifeCycleItem;
import com.sugon.entity.vo.SpartPartStatVO;
import com.sugon.entity.vo.SpartPartThjStatVO;
import com.sugon.modules.base.consts.BusModule;
import com.sugon.modules.base.consts.SysApproveStatusConst;
import com.sugon.modules.sparepart.consts.MaterialBaseConst;
import com.sugon.modules.sparepart.model.vo.SparePartApproveParamVO;
import com.sugon.modules.sparepart.service.ISparepartManager;
import com.sugon.service.*;
import com.sugon.utils.*;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 备件清单Controller
 *
 * @author sugon
 * @date 2019-07-17 09:37:19
 */
@Controller
@RequestMapping("sparepart")
public class SparePartController {
    @Resource
    private SparePartService sparePartService;
    @Resource
    private SparePartDao sparePartDao;
    @Resource
    private SpareStorePosService spareStorePosService;
    @Resource
    private SysUserService userService;
    @Resource
    private SysConfigService configService;
    @Resource
    private ISparepartManager sparepartManager;
    @Resource
    private SysMsgService sysMsgService;
    @Resource
    private DevTypeService devTypeService;
    @Resource
    private MaterialRecordDao materialRecordDao;
    @Resource
    private ScarpListDao scarpListDao;
    @Resource
    private SpareDevDao spareDevDao;
    @Resource
    private SparePartRequDetailDao sparePartRequDetailDao;
    @Resource
    private DevRetreadRecordDao devRetreadRecordDao;

    /**
     * 查看备件分类
     */
    @RequestMapping("/listCategory")
    @ResponseBody
    public R listCategory() {
        return R.ok().put("list", sparePartDao.listCategory());
    }

    /**
     * 查看备件单位列表
     */
    @RequestMapping("/listUnit")
    @ResponseBody
    public R getSparePartUnitList() {
        String sparePartUnit = configService.getValue("SPAREPART_UNIT", "");
        return R.ok().put("sparePartUnits", sparePartUnit.split(","));
    }

    /**
     * 查看备件安装部位列表
     */
    @RequestMapping("/listInstallPosition")
    @ResponseBody
    public R getSparePartInstallPositionList() {
        String sparePartUnit = configService.getValue("SPAREPART_INSTALL_POSITION", "");
        return R.ok().put("sparePartInstallPositions", sparePartUnit.split(","));
    }

    /**
     * 查看列表
     */
    @RequestMapping("/list")
//    @RequiresPermissions("sparepart:list")
    @ResponseBody
    public R list(@RequestParam Map<String, Object> params) {
        PageUtils pageUtil = sparepartManager.querySpareParts(params);
        return R.ok().put("page", pageUtil);
    }

    /**
     * 查看列表
     */
    @RequestMapping("/listSparePos")
    @ResponseBody
    public R listSparePos(@RequestParam Map<String, Object> params) {
        params.put("delFlag", 1);
        //查询列表数据
        Query query = new Query(params);
        List<SpareStorePosEntity> posList = spareStorePosService.queryList(query);

        int total = spareStorePosService.queryTotal(query);

        PageUtils pageUtil = new PageUtils(posList, total, query.getLimit(), query.getPage());

        return R.ok().put("page", pageUtil);
    }

    /**
     * 查看消耗统计
     */
    @RequestMapping("/getSpconsume")
    @ResponseBody
    public R getSpconsume(@RequestParam Map<String, Object> params) {
        //查询列表数据
        Query query = new Query(params);
        List<SparePartEntity> sparePartList = sparePartService.getSpconsume(query);
        int total = sparePartService.querySpconsumeTotal(query);
        PageUtils pageUtil = new PageUtils(sparePartList, total, query.getLimit(), query.getPage());
        return R.ok().put("page", pageUtil);
    }

    /**
     * 查看信息
     */
    @RequestMapping("/info/{id}")
    @RequiresPermissions("sparepart:info")
    @ResponseBody
    public R info(@PathVariable("id") String id) {
        // 校验备件是否存在
        SparePartEntity sparePart = sparePartService.queryObject(id);
        if (sparePart == null) {
            return R.error("备件不存在，请确认！");
        }
        /*
            是否可编辑
            可编辑：未审核通过 || 已审核通过的&& 特权用户
            不可编辑：其他
         */
        boolean isEditable = (!NumberUtil.equals(SysApproveStatusConst.PASSED, sparePart.getStatus()) || (NumberUtil.equals(SysApproveStatusConst.PASSED, sparePart.getStatus()) && userService.isPrivilegeUser(ShiroUtils.getUserId())));
        return R.ok().put("sparePart", sparePart).put("isEditable", isEditable);
    }

    /**
     * 获取备件统计信息
     * 包含近三年的领用统计、库存和在途数、自主维修中的、线边库中、委外维修中的
     *
     * @param id
     * @return
     */
    @RequestMapping("/getSparePartStat")
    @ResponseBody
    public R getSparePartStat(@RequestParam String id) {
        // 校验备件是否存在
        SparePartEntity sparePart = sparePartService.queryObject(id);
        if (sparePart == null) {
            return R.error("备件不存在，请确认！");
        }
        SpartPartStatVO spStat = new SpartPartStatVO(sparePart.getStockNum(), sparePart.getTransitNum());
        // 计算线边库数
        spStat.setXbkNum(materialRecordDao.countUnUsedLyNum(CollectionUtil.newArrayList(id), CollectionUtil.newArrayList(MaterialBaseConst.COMMON_MATERIAL, MaterialBaseConst.XF)));
        // 计算自主维修数：只统计待维修中的
        spStat.setZzwxQuantity(devRetreadRecordDao.countSpZzwxNum(CollectionUtil.newArrayList(id), CollectionUtil.newArrayList(DevRetreadStatus.CJ_ING.getValue(), DevRetreadStatus.PE_ING.getValue())));
        // 计算委外维修数
        spStat.setWwwxQuantity(devRetreadRecordDao.countSpZzwxNum(CollectionUtil.newArrayList(id), CollectionUtil.newArrayList(DevRetreadStatus.WWXF.getValue())));
        // 计算近三年的备件领用数
        spStat.setYearlyLyItems(sparepartManager.queryLastYearLyStat(id, 3));
        return R.ok().put("statResult", spStat);
    }

    /**
     * 获取备件替换件的统计信息
     * 包含：库存数量、在途数量、线边库数量、自主维修数量，委外维修数量，需求计划数量
     *
     * @param id
     * @return
     */
    @RequestMapping("/getSpThjStat")
    @ResponseBody
    public R getSpThjStat(@RequestParam String id) {
        // 校验备件是否存在
        SparePartEntity sparePart = sparePartService.queryObject(id);
        if (sparePart == null) {
            return R.error("备件不存在，请确认！");
        }
        SpartPartThjStatVO spStat = new SpartPartThjStatVO(0, 0);
        // 获取备件的替换件
        List<String> thjIdList = spareDevDao.queryListThjList(id);
        if (CollectionUtil.isNotEmpty(thjIdList)) {
            // 获取对应的替换件信息
            List<SparePartEntity> spList = sparePartDao.queryListByIdList(thjIdList);
            if (CollectionUtil.isNotEmpty(spList)) {
                // 库存数量
                spStat.setStockNum(spList.stream().filter(sp -> sp.getStockNum() != null).map(SparePartEntity::getStockNum).reduce(0, (a, b) -> a + b));
                // 在途数量
                spStat.setTransitNum(spList.stream().filter(sp -> sp.getTransitNum() != null).map(SparePartEntity::getTransitNum).reduce(0, (a, b) -> a + b));
            }
            // 计算线边库数
            spStat.setXbkNum(materialRecordDao.countUnUsedLyNum(thjIdList, CollectionUtil.newArrayList(MaterialBaseConst.COMMON_MATERIAL, MaterialBaseConst.XF)));
            // 计算自主维修数
            spStat.setZzwxQuantity(devRetreadRecordDao.countSpZzwxNum(CollectionUtil.newArrayList(id), CollectionUtil.newArrayList(DevRetreadStatus.CJ_ING.getValue(), DevRetreadStatus.PE_ING.getValue())));
            // 计算委外维修数
            spStat.setWwwxQuantity(devRetreadRecordDao.countSpZzwxNum(CollectionUtil.newArrayList(id), CollectionUtil.newArrayList(DevRetreadStatus.WWXF.getValue())));
            // 需求计划数量
            spStat.setXqjhQuantity(sparePartRequDetailDao.sumDemandNum(null, thjIdList));
        }
        return R.ok().put("statResult", spStat);
    }

    /**
     * 获取备件生命周期明细
     *
     * @param id
     * @return
     */
    @RequestMapping("/lifeCycle")
    @ResponseBody
    public R getSpLifeCycle(@RequestParam String id) {
        // 校验备件是否存在
        SparePartEntity sparePart = sparePartService.queryObject(id);
        if (sparePart == null) {
            return R.error("备件不存在，请确认！");
        }
        List<SparePartLifeCycleItem> lifeCycleItemList = sparePartDao.loadLifeCycleItem(id);
        return R.ok().put("list", Optional.ofNullable(lifeCycleItemList).orElse(CollectionUtil.newArrayList()));
    }

    /**
     * 保存
     */
    @LimitSubmit(key = "saveSparePart:%s")
    @AutoLog(value = "添加", busModule = BusModule.SPARE_PARTS)
    @RequestMapping("/save")
    @RequiresPermissions("sparepart:save")
    @ResponseBody
    public R save(@RequestBody SparePartEntity sparePart) {
        // 现场装机总量必填
        if (StrUtil.isEmpty(sparePart.getReserve1())) {
            return R.error("现场装机总量必填！");
        }
        // 必须指定ABC类
        if (StrUtil.isEmpty(sparePart.getPlanAbc())) {
            return R.error("必须指定ABC类！");
        }
        // 校验同样的备件名称和规格是否存在
        List<String> matchedList = sparePartDao.queryPerfectMatchedTotal(BeanUtil.beanToMap(sparePart));
        if (CollectionUtil.isNotEmpty(matchedList)) {
            return R.error("已存在同样的备件名称和规格，请确认！");
        }
        // 只能关联设备小类
        if (StrUtil.isNotEmpty(sparePart.getDevType())) {
            if (StrUtil.length(sparePart.getDevType()) != 6) {
                return R.error("只能关联设备小类！");
            }
            DevTypeEntity devType = devTypeService.queryObjectByCode(sparePart.getDevType());
            if (devType == null) {
                return R.error("设备分类不存在，请确认！");
            }
        }
        return sparePartService.save(sparePart) > 0 ? R.ok() : R.error();
    }

    /**
     * 修改
     */
    @LimitSubmit(key = "updateSparePart:%s")
    @AutoLog(value = "编辑", busModule = BusModule.SPARE_PARTS)
    @RequiresPermissions("sparepart:update")
    @RequestMapping("/update")
    @ResponseBody
    public R update(@RequestBody SparePartEntity sparePart) {
        // 现场装机总量必填
        if (StrUtil.isEmpty(sparePart.getReserve1())) {
            return R.error("现场装机总量必填！");
        }
        // 必须指定ABC类
        if (StrUtil.isEmpty(sparePart.getPlanAbc())) {
            return R.error("必须指定ABC类！");
        }
        // 校验同样的备件名称和规格是否存在
        List<String> matchedList = sparePartDao.queryPerfectMatchedTotal(BeanUtil.beanToMap(sparePart));
        if (CollectionUtil.isNotEmpty(matchedList)) {
            return R.error("已存在同样的备件名称和规格，请确认！");
        }
        // 已审批通过的备件除特权用户外不允许修改
        SparePartEntity sparePartInDB = sparePartService.queryObject(sparePart.getId());
        if (!userService.isPrivilegeUser(ShiroUtils.getUserId()) && (sparePartInDB.getStatus() == SysApproveStatusConst.PASSED)) {
            return R.error("当前备件已审批通过，禁止更改！");
        }
        if (sparePartInDB.getStatus() != SysApproveStatusConst.PASSED) {
            sparePart.setStatus(SysApproveStatusConst.NOT_YET_APPROVE);
        } else {
            // 不允许更新备件状态
            sparePart.setStatus(null);
        }
        // 只能关联设备小类
        if (StrUtil.isNotEmpty(sparePart.getDevType())) {
            if (StrUtil.length(sparePart.getDevType()) != 6) {
                return R.error("只能关联设备小类！");
            }
            DevTypeEntity devType = devTypeService.queryObjectByCode(sparePart.getDevType());
            if (devType == null) {
                return R.error("设备分类不存在，请确认！");
            }
        }
        boolean flag = sparePartService.update(sparePart) > 0;
        if (flag) {
            if (sparePartInDB.getStatus() == SysApproveStatusConst.NOT_PASSED) {
                // 添加审批消息
                sysMsgService.generateSparePartApproveItemMsg(sparePart.getId(), 0);
            }
        }
        return flag ? R.ok() : R.error();
    }

    /**
     * 调整备件图片
     */
    @LimitSubmit(key = "updateSpImage:%s")
    @RequestMapping("/updateImage")
    @ResponseBody
    public R updateSpImage(@RequestBody SparePartEntity sparePart) {
        return sparePartService.update(sparePart) > 0 ? R.ok() : R.error();
    }

    /**
     * 删除
     */
    @AutoLog(value = "删除", busModule = BusModule.SPARE_PARTS)
    @RequestMapping("/delete")
    @RequiresPermissions("sparepart:delete")
    @ResponseBody
    public R delete(@RequestBody String[] ids) {
        // 获取用户是否是特权用户
        boolean isPrivilege = userService.isPrivilegeUser(ShiroUtils.getUserId());
        for (String id : ids) {
            // 已审批通过的备件除特权用户外不允许修改
            SparePartEntity sparePartEntity = sparePartService.queryObject(id);
            if (!isPrivilege && (sparePartEntity.getStatus() == 1)) {
                return R.error("当前备件已审批通过，禁止更改！");
            }
        }
        return sparePartService.deleteBatch(ids) > 0 ? R.ok() : R.error();
    }

    /**
     * 查看所有列表
     */
    @RequestMapping("/queryAll")
    @ResponseBody
    public R queryAll(@RequestParam Map<String, Object> params) {
        List<SparePartEntity> list = sparePartDao.queryList(params);
        return R.ok().put("list", list);
    }

    /**
     * 根据备件名称、规格查询是否已存在
     * 备件名称、规格 不允许重复
     * ERP编码 不允许重复
     */
    @RequestMapping("/isExists")
    @ResponseBody
    public R isExists(@RequestParam Map<String, Object> params) {
        String rows = "";
        List<String> matchedList = sparePartDao.queryPerfectMatchedTotal(params);
        if (CollectionUtil.isNotEmpty(matchedList)) {
            String suffix = "";
            if (matchedList.size() > 2) {
                matchedList = CollectionUtil.sub(matchedList, 0, 2);
                suffix = "等";
            }
            rows = CollectionUtil.join(matchedList, "，") + suffix;
        }
        return R.ok().put("rows", rows);
    }

    /**
     * 获取条数
     */
    @RequestMapping("/count")
    @ResponseBody
    public R count(@RequestParam Map<String, Object> params) {
        int total = sparePartService.queryTotal(params);
        return R.ok().put("total", total);
    }

    @NonBusinessParamValid
    @RequestMapping("/Approval")
    @ResponseBody
    public R approval(@Validated @RequestBody SparePartApproveParamVO sparePart, BindingResult bindingResult) {
        return sparepartManager.batchApprove(sparePart) ? R.ok() : R.error();
    }

    @AutoLog(value = "导出", busModule = BusModule.SPARE_PARTS)
    @RequestMapping("/export")
    @RequiresPermissions("sparepart:export")
    @ResponseBody
    public void export(@RequestParam Map<String, Object> params, ModelMap modelMap, HttpServletRequest request, HttpServletResponse response) throws FileNotFoundException {
        // 查询工装清单列表
        MapUtil.removeEmptyValue(params);
        List<SparePartEntity> sparePartList = sparePartService.queryList(params);
        Map<String, Object> map = new HashMap<>(1);
        map.put("sparePartList", sparePartList);
        // 构建模板导出参数
        TemplateExportParams templateExportParams = new TemplateExportParams(configService.getPoiTemplatePath() + "sparePartIETemplate.xlsx");
        templateExportParams.setColForEach(true);

        modelMap.put(TemplateExcelConstants.FILE_NAME, "备件基础信息_" + com.sugon.modules.utils.DateUtil.today());
        modelMap.put(TemplateExcelConstants.PARAMS, templateExportParams);
        modelMap.put(TemplateExcelConstants.MAP_DATA, map);
        PoiBaseView.render(modelMap, request, response, TemplateExcelConstants.EASYPOI_TEMPLATE_EXCEL_VIEW);
    }

    /**
     * excel导入
     */
    @AutoLog(value = "导入", busModule = BusModule.SPARE_PARTS)
    @RequestMapping("/import")
    @RequiresPermissions("sparepart:import")
    @ResponseBody
    public R importE(@RequestParam("file") MultipartFile file) throws Exception {
        if (file.isEmpty()) {
            throw new RRException("上传文件不能为空");
        }
        int count = sparePartService.importE(file);
        return R.ok("成功导入" + count + "条数据");
    }
}
